#from django.http import HttpResponse
from django.shortcuts import render_to_response#, get_object_or_404
from django.template import RequestContext
from lingcod.raster_stats.models import RasterDataset, zonal_stats
from lingcod.unit_converter.models import convert_float_to_area_display_units
from analysis.utils import convert_sq_km_to_sq_mi, convert_cm_to_in, get_terra_geom, get_oceanic_geom
from analysis.caching.report_caching import *
from analysis.models import ExtinctLanguages, SeaRise1m, SeaRise3m, SeaRise6m, PovertyNoData
from analysis.summary.summary_analysis import get_population
#from settings import *

default_value = '---'
uw5_total = 115000000. #http://www.who.int/whosis/whostat/EN_WHS2011_Part1.pdf 
u5_total = 642000000.
worlds_population = 7000000000.
worlds_population_in_poverty = 1700000000.
sea_level_grid_size = 858.8379471 * 858.8379471

'''
Run the analysis, create the cache, and return the results as a context dictionary so they may be rendered with template
'''    
def display_climate_analysis(request, bioregion, template='vulnerability/climate_report.html'):
    #get human vulnerabilities to climate change
    climate_impact = get_climate_change_vulnerability(bioregion) 
    #get anticipated temperature change by 2050
    temp_change = get_temp_change(bioregion)
    #get impact on agricultural production
    ag_impacts = get_agricultural_impacts(bioregion)
    #get impact on water resources
    water_impacts = get_water_impacts(bioregion)
    #get anticipated land loss due to sea level rise (1m, 3m, 6m)
    land_loss_1m, land_loss_3m, land_loss_6m = get_sea_rise_impacts(bioregion) #39 seconds
    #get affected people due to sea level rise
    #displaced_pop_1m, displaced_pop_3m, displaced_pop_6m = get_displaced_populations(bioregion)
    #compile context
    context = {'bioregion': bioregion, 'default_value': default_value, 'climate_impact': climate_impact, 'temp_change': temp_change, 'ag_impacts': ag_impacts, 'water_impacts': water_impacts, 'land_loss_1m': land_loss_1m, 'land_loss_3m': land_loss_3m, 'land_loss_6m': land_loss_6m} #, 'displaced_pop_1m': displaced_pop_1m, 'displaced_pop_3m': displaced_pop_3m, 'displaced_pop_6m': displaced_pop_6m}
    return render_to_response(template, RequestContext(request, context)) 
    
'''
Run the analysis, create the cache, and return the results as a context dictionary so they may be rendered with template
'''    
def display_socioeconomic_analysis(request, bioregion, template='vulnerability/socioeconomic_report.html'):
    #get human influence index (HII)  (0-64, low to high) -- area of land developed
    human_influence = get_human_influence(bioregion) #50 seconds
    #get human consumption (HANPP - Human Appropriation of Net Primary Productivity)
    #represents regions in which human consumption is greatly in excess of local ecosystems
    human_consumption = get_human_consumption(bioregion) #2 seconds
    #get global impact of marine ecosystems
    marine_impacts = get_marine_ecosystem_impacts(bioregion) #15 seconds
    #get human presence (built up land - light signatures and landuse) (0-100, low to high)
    #human_presence = get_human_presence(bioregion)
    #get soil suitability
    soil_suitability = get_soil_suitability(bioregion) #1 second 
    #get water stress (ration of human water use to renewable water resources)
    rws_index, rws_rating = get_water_stress(bioregion) #2 seconds 
    #percentage of population    
    population_2005 = get_population(bioregion) #7 seconds 
    #get infant deaths
    #infant_deaths = get_infant_deaths(bioregion)
    #get underweight children (number of underweight children under the age of 5)
    underweight_children = get_underweight_children(bioregion) #7 seconds
    perc_underweight_children = underweight_children / uw5_total #this value is the sum total of all underweight children 
    #perc_impoverished = uw5_total / u5_total #(total uw5 / total <5)
    #estimated_impoverished = perc_underweight_children * perc_impoverished * worlds_population
    if perc_underweight_children > 0:
        estimated_impoverished = int(perc_underweight_children * worlds_population_in_poverty)
    else:
        estimated_impoverished = 0
    if population_2005 == 0:
        estimated_perc_impoverished = 0
    else:
        estimated_perc_impoverished = estimated_impoverished / float(population_2005)
    #report out a 'No Data' if estimated_impoverished is 0.0
    #get extinct languages
    extinct_languages = get_extinct_languages(bioregion) #1 second 
    #compile context
    context = {'bioregion': bioregion, 'default_value': default_value, 'underweight_children': underweight_children, 'perc_underweight_children': perc_underweight_children, 'estimated_impoverished': estimated_impoverished, 'estimated_perc_impoverished': estimated_perc_impoverished, 'human_consumption': human_consumption, 'human_influence': human_influence, 'marine_impacts': marine_impacts, 'soil_suitability': soil_suitability, 'rws_index': rws_index, 'rws_rating': rws_rating, 'extinct_languages': extinct_languages}
    return render_to_response(template, RequestContext(request, context)) 
      
'''
Run the analysis, create the cache, and return the results as a context dictionary so they may be rendered with template
'''    
def display_hazards_analysis(request, bioregion, template='vulnerability/hazards_report.html'):
    #hazrd codes:  drgt: drought, fld: flood, vol: volcano, pga: earthquake, cyc: cyclone, lnd: landslide
    #hzrd_xxx for frequency and distribution, xxx_gdp for economic impact 
    #get likely and unlikely hazards
    likely_hazards, unlikely_hazards = get_hazard_lists(bioregion)
    #compile context
    context = {'bioregion': bioregion, 'default_value': default_value, 'likely_hazards': likely_hazards, 'unlikely_hazards': unlikely_hazards}
    return render_to_response(template, RequestContext(request, context)) 

def get_climate_change_vulnerability(bioregion):
    cc_geom = RasterDataset.objects.get(name='climate_impact')
    cc_stats = zonal_stats(bioregion.output_geom, cc_geom)
    if cc_stats.avg:
        if cc_stats.avg < -12: index = 'Low'
        elif cc_stats.avg < -4: index = 'Moderately Low'
        elif cc_stats.avg < 4: index = 'Moderate'
        elif cc_stats.avg < 12: index = 'Moderately High'
        else: index = 'High'
        return (index, cc_stats.avg)
    else:
        return default_value
    
def get_temp_change(bioregion):
    tc_geom = RasterDataset.objects.get(name='temp_change')
    tc_stats = zonal_stats(bioregion.output_geom, tc_geom)
    if tc_stats.avg:
        temp_c = tc_stats.avg
        temp_f = temp_c * 1.8
        return (temp_c, temp_f)
    else:
        return default_value
    
def get_agricultural_impacts(bioregion):
    terra_geom = get_terra_geom(bioregion)
    if terra_geom.area == 0.0:
        return [default_value]
    ag_geom = RasterDataset.objects.get(name='ag_impacts')
    ag_stats = zonal_stats(terra_geom, ag_geom)
    if ag_stats.pixels:
        total_pixels = float(ag_stats.pixels)
        categories = ag_stats.categories.all()
        impacts_dict = {}
        for cat in categories:
            impacts_dict[cat.category] = cat.count
        perc_impacts = []
        for cat, count in impacts_dict.items():
            perc_impacts.append( (count/total_pixels, cat) )
        perc_impacts.sort(reverse=True)
        final_impacts = []
        for impact in perc_impacts:
            if impact[1] == 0:
                final_impacts.append(('No Data', impact[0]))
                if impact[0] > .9:
                    final_impacts = [default_value]
                    break
            elif impact[1] == 1:
                final_impacts.append(('a Major Increase in Production', impact[0]))
            elif impact[1] == 2:
                final_impacts.append(('an General Increase in Production', impact[0]))
            elif impact[1] == 3:
                final_impacts.append(('a Slight Increase in Production', impact[0]))
            elif impact[1] == 4:
                final_impacts.append(('a Slight Decrease in Production', impact[0]))
            elif impact[1] == 5:
                final_impacts.append(('a General Decrease in Production', impact[0]))
            elif impact[1] == 6:
                final_impacts.append(('a Major Decrease in Production', impact[0]))
        return final_impacts
    else:
        return [default_value]
    
def get_water_impacts(bioregion):
    wi_geom = RasterDataset.objects.get(name='water_impacts')
    wi_stats = zonal_stats(bioregion.output_geom, wi_geom)
    if wi_stats.pixels:
        total_pixels = float(wi_stats.pixels)
        categories = wi_stats.categories.all()
        impacts_dict = {}
        for cat in categories:
            impacts_dict[cat.category] = cat.count
        perc_impacts = []
        for cat, count in impacts_dict.items():
            perc_impacts.append( (count/total_pixels, cat) )
        perc_impacts.sort(reverse=True)
        final_impacts = []
        for impact in perc_impacts:
            if impact[1] == 0:
                final_impacts.append(('Less Precipitation', impact[0]))
            elif impact[1] == 1:
                final_impacts.append(('No Significant Change in Precipitation', impact[0]))
            elif impact[1] == 2:
                final_impacts.append(('More Precipitation', impact[0]))
        return final_impacts
    else:
        return [default_value]
    
    
def get_sea_rise_impacts(bioregion):
    s1_geom = RasterDataset.objects.get(name='sea_rise_1m')
    s3_geom = RasterDataset.objects.get(name='sea_rise_3m')
    s6_geom = RasterDataset.objects.get(name='sea_rise_6m')
    s1_stats = zonal_stats(bioregion.output_geom, s1_geom)
    s3_stats = zonal_stats(bioregion.output_geom, s3_geom)
    s6_stats = zonal_stats(bioregion.output_geom, s6_geom)
    land_loss_1m = s1_stats.sum * sea_level_grid_size
    land_loss_3m = s3_stats.sum * sea_level_grid_size
    land_loss_6m = s6_stats.sum * sea_level_grid_size
    land_loss_1m_km = int(convert_float_to_area_display_units(land_loss_1m))
    land_loss_1m_mi = int(convert_sq_km_to_sq_mi(land_loss_1m_km))
    land_loss_3m_km = int(convert_float_to_area_display_units(land_loss_3m))
    land_loss_3m_mi = int(convert_sq_km_to_sq_mi(land_loss_3m_km))
    land_loss_6m_km = int(convert_float_to_area_display_units(land_loss_6m))
    land_loss_6m_mi = int(convert_sq_km_to_sq_mi(land_loss_6m_km))
    return (land_loss_1m_km, land_loss_1m_mi), (land_loss_3m_km, land_loss_3m_mi), (land_loss_6m_km, land_loss_6m_mi)
    
def get_displaced_populations(bioregion):
    pop_geom = RasterDataset.objects.get(name='population_2005')
    pop_stats = zonal_stats(bioregion.output_geom, pop_geom)    
    pop_05_sum = pop_stats.sum
    if pop_05_sum in [None, 0]:
        return (0,0), (0,0), (0,0)
    
    if report_cache_exists(bioregion, 'displaced_people_1m'):
        displaced_1m = get_report_cache(bioregion, 'displaced_people_1m')
    else:
        sr_objects = SeaRise1m.objects.filter(geometry__bboverlaps=bioregion.output_geom)  #.aggregate(Collect('geometry'))
        displaced_1m = get_displaced(pop_geom, pop_stats, pop_05_sum, sr_objects, bioregion)
        create_report_cache(bioregion, dict(displaced_people_1m=displaced_1m))
    
    if report_cache_exists(bioregion, 'displaced_people_3m'):
        displaced_3m = get_report_cache(bioregion, 'displaced_people_3m')
    else:
        sr_objects = SeaRise3m.objects.filter(geometry__bboverlaps=bioregion.output_geom)  #.aggregate(Collect('geometry'))
        displaced_3m = get_displaced(pop_geom, pop_stats, pop_05_sum, sr_objects, bioregion)
        create_report_cache(bioregion, dict(displaced_people_3m=displaced_3m))
    
    if report_cache_exists(bioregion, 'displaced_people_6m'):
        displaced_6m = get_report_cache(bioregion, 'displaced_people_6m')
    else:
        sr_objects = SeaRise6m.objects.filter(geometry__bboverlaps=bioregion.output_geom)  #.aggregate(Collect('geometry'))
        displaced_6m = get_displaced(pop_geom, pop_stats, pop_05_sum, sr_objects, bioregion)
        create_report_cache(bioregion, dict(displaced_people_6m=displaced_6m))
        
    return displaced_1m, displaced_3m, displaced_6m
    
def get_displaced(pop_geom, pop_stats, pop_05_sum, sr_objects, bioregion):
    sr_geoms = [sr.geometry.intersection(bioregion.output_geom) for sr in sr_objects if sr.geometry.intersects(bioregion.output_geom)] 
    sum_pop = 0
    for sr_geom in sr_geoms:
        if not sr_geom.valid:
            sr_geom = sr_geom.buffer(0)
        pop_stats = zonal_stats(sr_geom, pop_geom)
        if pop_stats.sum:
            sum_pop += pop_stats.sum
    perc_pop = sum_pop / pop_05_sum
    sum_pop = int(sum_pop / 1000) * 1000
    return (sum_pop, perc_pop)   
    
    
def get_human_consumption(bioregion):
    hc_geom = RasterDataset.objects.get(name='human_consumption')
    hc_stats = zonal_stats(bioregion.output_geom, hc_geom)
    if hc_stats.avg:
        return int(hc_stats.avg)
    else:
        return default_value
    
def get_marine_ecosystem_impacts(bioregion):
    oceanic_geom = get_oceanic_geom(bioregion)
    if oceanic_geom.area == 0:
        return 0
    mi_geom = RasterDataset.objects.get(name='ocean_impact')
    mi_stats = zonal_stats(oceanic_geom, mi_geom)
    if mi_stats.avg:
        avg = round(mi_stats.avg, 1)
        if avg < 1.4:
            impact = 'Very Low'
        elif avg < 4.95:
            impact = 'Low'
        elif avg < 8.47:
            impact = 'Medium'
        elif avg < 12:
            impact = 'Medium High'
        elif avg < 15.52:
            impact = 'High'
        else:
            impact = 'Very High'
        return impact
    return default_value
'''   
def get_human_presence(bioregion):
    hp_geom = RasterDataset.objects.get(name='human_presence')
    hp_stats = zonal_stats(bioregion.output_geom, hp_geom)
    return int(hp_stats.avg)
''' 
'''  
def get_human_footprint(bioregion):
    hf_geom = RasterDataset.objects.get(name='human_footprint')
    hf_stats = zonal_stats(bioregion.output_geom, hf_geom)
    return int(hf_stats.avg)
'''   
def get_human_influence(bioregion):
    hii_geom = RasterDataset.objects.get(name='human_influence_index')
    hii_stats = zonal_stats(bioregion.output_geom, hii_geom)
    if hii_stats.avg:       
        return hii_stats.avg / 64
    else:
        return default_value
   
def get_water_stress(bioregion):
    ws_geom = RasterDataset.objects.get(name='water_stress')
    ws_stats = zonal_stats(bioregion.output_geom, ws_geom)
    if ws_stats.avg:
        rwsi = ws_stats.avg
        if rwsi >= 3.5:
            rating = 'High'
        elif rwsi >= 2.5:
            rating = 'Moderate'
        elif rwsi >= 1.5:
            rating = 'Low'
        else:
            rating = 'Unstressed'
        return rwsi, rating
    return default_value, default_value
   
def get_soil_suitability(bioregion):
    suit_geom = RasterDataset.objects.get(name='soil_suitability')
    suit_stats = zonal_stats(bioregion.output_geom, suit_geom)
    if suit_stats.avg:    
        return suit_stats.avg
    else:
        return default_value
    
def get_infant_deaths(bioregion):
    id_geom = RasterDataset.objects.get(name='infant_deaths')
    id_stats = zonal_stats(bioregion.output_geom, id_geom)
    return int(id_stats.sum)
   
def get_underweight_children(bioregion):
    if no_poverty_data(bioregion, .1):
        return 0
    uwc_geom = RasterDataset.objects.get(name='underweight_children')
    uwc_stats = zonal_stats(bioregion.output_geom, uwc_geom)
    if uwc_stats.sum:
        return int(uwc_stats.sum)
    else:
        return 0
        
def no_poverty_data(bioregion, threshold):
    if report_cache_exists(bioregion, 'nopov_perc'):
        nopov_perc = get_report_cache(bioregion, 'nopov_perc')
        if nopov_perc >= threshold:
            return True
        else:
            return False
    else:
        nopov_regions = PovertyNoData.objects.filter(geometry__bboverlaps=bioregion.output_geom)
        nopov_areas = [region.geometry.intersection(bioregion.output_geom).area for region in nopov_regions if region.geometry.intersects(bioregion.output_geom)]
        nopov_area = 0
        for area in nopov_areas:
            nopov_area += area
        terra_geom = get_terra_geom(bioregion)
        nopov_perc = nopov_area / terra_geom.area
        create_report_cache(bioregion, dict(nopov_perc=nopov_perc))
        if nopov_perc >= threshold:
            return True
        else:
            return False
    
def get_hazard_lists(bioregion):
    likely_hazards = []
    unlikely_hazards = []
    hazards = ['cyclone', 'drought', 'flood', 'landslide', 'earthquake', 'volcano']
    for hazard in hazards:
        cost = hazard_impact(hazard, bioregion)
        if hazard_is_likely(hazard, bioregion):
            likely_hazards.append((hazard.capitalize(), cost))
        else:
            unlikely_hazards.append((hazard.capitalize(), cost))
    likely_hazards.sort()
    unlikely_hazards.sort()
    return likely_hazards, unlikely_hazards
            
def hazard_impact(hazard, bioregion):
    hzd_gdp_geom = RasterDataset.objects.get(name=hazard+'_impact')
    hzd_gdp_stats = zonal_stats(bioregion.output_geom, hzd_gdp_geom)
    if hzd_gdp_stats.sum > 0:
        return 'High'
    else:
        return 'Low'
        
def hazard_is_likely(hazard, bioregion):
    hzd_geom = RasterDataset.objects.get(name=hazard)
    hzd_stats = zonal_stats(bioregion.output_geom, hzd_geom)
    if hzd_stats.sum > 0:
        return True
    else:
        return False
        
def get_extinct_languages(bioregion):
    if report_cache_exists(bioregion, 'extinct_languages'):
        lang_tuples = get_report_cache(bioregion, 'extinct_languages')
        return lang_tuples
    else:
        languages = ExtinctLanguages.objects.all()
        lang_tuples = [(lang.nam_ansi, int(lang.lmp_pop1)) for lang in languages if lang.geometry.intersects(bioregion.output_geom)]
        lang_tuples.sort()
        create_report_cache(bioregion, dict(extinct_languages=lang_tuples))
        return lang_tuples    

   